`timescale 1ns/1ps
module scratchpad_mem_tb();
	parameter	S_DATA_WIDTH	= 20	;		// --- scratch memory data width ---
	parameter	S_NUM_ROWS		= 26	;		// --- scratch memory row numbers ---
	parameter	S_NUM_COLS		= 4		;		// --- scratch memory col numbers ---
	parameter	C_NUM_BYTES		= 64	;		// --- number of bytes in a cache line ---
	parameter	GRC_WIDTH		=	(S_NUM_ROWS <= 2)	 ? 1  :
									(S_NUM_ROWS <= 4)    ? 2  :
									(S_NUM_ROWS <= 8)    ? 3  :
									(S_NUM_ROWS <= 16)   ? 4  :
									(S_NUM_ROWS <= 32)   ? 5  :
									(S_NUM_ROWS <= 64)   ? 6  :
									(S_NUM_ROWS <= 128)  ? 7  :
									(S_NUM_ROWS <= 256)  ? 8  :
									(S_NUM_ROWS <= 512)  ? 9  :
									(S_NUM_ROWS <= 1024) ? 10 :
									(S_NUM_ROWS <= 2048) ? 11 :
									(S_NUM_ROWS <= 4096) ? 12 :
									(S_NUM_ROWS <= 8192) ? 13 : 14;
	parameter	GCC_WIDTH		= 	(S_NUM_COLS <= 2) 	 ? 1  :
									(S_NUM_COLS <= 4)    ? 2  :
									(S_NUM_COLS <= 8)    ? 3  :
									(S_NUM_COLS <= 16)   ? 4  :
									(S_NUM_COLS <= 32)   ? 5  :
									(S_NUM_COLS <= 64)   ? 6  :
									(S_NUM_COLS <= 128)  ? 7  :
									(S_NUM_COLS <= 256)  ? 8  :
									(S_NUM_COLS <= 512)  ? 9  :
									(S_NUM_COLS <= 1024) ? 10 :
									(S_NUM_COLS <= 2048) ? 11 :
									(S_NUM_COLS <= 4096) ? 12 :
									(S_NUM_COLS <= 8192) ? 13 : 14;
	// Buffer
	reg									clk				;
	reg									config_en		;
	reg									config_mode		;
	reg									new_frame		;
	reg									new_config		;
	reg		[GRC_WIDTH : 0]				image_height	;
	reg		[GCC_WIDTH : 0]				image_width		;
	reg									src_valid_in	;
	reg		[S_DATA_WIDTH-1 : 0]		data_in			;
	reg									s_rden			;
	reg		[GRC_WIDTH-1 : 0]			s_row			;
	reg		[GCC_WIDTH-1 : 0]			s_col			;

	wire	[S_DATA_WIDTH-1 : 0]		s_dout			;
	wire								s_dout_valid	;

	// Cache
	reg									c_config_en		;
	reg		[31 : 0]					c_id			;
	reg									c_wren			;
	reg		[C_NUM_BYTES*8-1 : 0]		c_din			;
	reg		[GCC_WIDTH-1 : 0]			c_addr			;
	reg									c_rden			;
	
	wire	[C_NUM_BYTES*8-1 : 0]		c_dout			; 
	wire								c_dout_valid	;

	initial begin
		clk				= 1'b0;
		config_en		= 1'b0;
		config_mode		= 1'b0;
		new_frame		= 1'b0;
		new_config		= 1'b0;
		image_height	= 32'd0;
		image_width		= 32'd0;
		src_valid_in	= 1'b0;
		data_in			= 32'd0;
		s_rden			= 1'b0;
		s_row			= 32'd0;
		s_col			= 32'd0;

		c_config_en		= 1'b0;
		c_id			= 32'd0;
		c_wren			= 1'b0;
		c_din			= 40'd0;
		c_addr			= 32'd0;
		c_rden			= 1'b0;

		#1003
		config_en		= 1'b1;
		config_mode		= 1'b0;
		#10
		config_en		= 1'b0;
		new_config		= 1'b1;
		image_height	= 32'd26;		// need to change
		image_width		= 32'd4;		// need to change
		#10
		new_config		= 1'b0;
		new_frame		= 1'b1;
		#10
		new_frame		= 1'b0;

		#100
		src_valid_in	= 1'b1;
		data_in			= 32'd1;
		#10
		data_in			= 32'd2;
		#10
		data_in			= 32'd3;
		#10
		data_in			= 32'd4;
		#10
		data_in			= 32'd5;
		#10
		data_in			= 32'd6;
		#10
		data_in			= 32'd7;
		#10
		data_in			= 32'd8;
		#10
		data_in			= 32'd9;
		#10
		data_in			= 32'd10;
		#10
		data_in			= 32'd11;
		#10
		data_in			= 32'd12;
		#10
		data_in			= 32'd13;
		#10
		data_in			= 32'd14;
		#10
		data_in			= 32'd15;
		#10
		data_in			= 32'd16;
		#10
		data_in			= 32'd17;
		#10
		data_in			= 32'd18;
		#10
		data_in			= 32'd19;
		#10
		data_in			= 32'd20;
		#10
		src_valid_in	= 1'b0;
		#100
		s_rden			= 1'b1;
		s_row			= 32'd0;
		s_col			= 32'd1;
		#10
		s_row			= 32'd1;
		s_col			= 32'd1;
		#10
		s_row			= 32'd2;
		s_col			= 32'd1;
		#10
		s_row			= 32'd3;
		s_col			= 32'd1;
		#10
		s_rden			= 1'b0;
		#100	
		config_en		= 1'b1;
		config_mode		= 1'b1;
		#10
		config_en		= 1'b0;
		c_config_en		= 1'b1;
		c_id			= 32'd3;
		#10
		c_config_en		= 1'b0;
		c_wren			= 1'b1;
		c_addr			= 32'd1;
		c_din			= 512'hFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF;
		#10
		c_addr			= 32'd2;
		c_din			= 512'hAAAA_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA;
		#10
		c_wren			= 1'b0;
		#10
		c_rden			= 1'b1;
		c_addr			= 32'd1;
		#10
		c_addr			= 32'd2;
		#10
		c_rden			= 1'b0;
		#1000
		$finish;
	end

	always begin
		#5	
		clk				= !clk;
	end

	scratchpad_mem #(
		.S_DATA_WIDTH		(S_DATA_WIDTH	),
		.S_NUM_ROWS			(S_NUM_ROWS		),
		.S_NUM_COLS			(S_NUM_COLS		),
		.C_NUM_BYTES		(C_NUM_BYTES	)
	)
	scratchpad_mem_inst (
		.clk				(clk			),
		.config_en			(config_en		),
		.config_mode		(config_mode	),
		.new_frame			(new_frame		),
		.new_config			(new_config		),
		.image_height		(image_height	),
		.image_width		(image_width	),
		.src_valid_in		(src_valid_in	),
		.data_in			(data_in		),
		.s_rden				(s_rden			),
		.s_row				(s_row			),
		.s_col				(s_col			),
		.c_config_en		(c_config_en	),
		.c_id				(c_id			),
		.c_wren				(c_wren			),
		.c_din				(c_din			),
		.c_addr				(c_addr			),
		.c_rden				(c_rden			),
	
											
		.s_dout				(s_dout			),
		.s_dout_valid		(s_dout_valid	),
		.c_dout				(c_dout			),
		.c_dout_valid		(c_dout_valid	)
	);

endmodule
